#define MSDENC_C
/*----------------------------------------------*
 * include files            	 *
 *----------------------------------------------*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <libmslog/mslog.h>
#include "mscommon.h"
#include "msstring.h"
#include "mstime.h"
#include "msmd5.h"
#include "msdenc.h"


/*----------------------------------------------*
 * macros                               *
 *----------------------------------------------*/
#define FLAG "msdenc"

#define enp_exstring_super "key=200812021&string=msavskit&info=supercapacity"

#define KEYNAME_TIMECODE		"sinnum="	
#define KEYNAME_KEYCODE			"sernum="

#define MAXLEN_DENC_CONTENT	32768					//MD5计算时最大支持的content数据长度
#define LEN_MD5DATA	(MAXLEN_DENC_CONTENT+512)		//512预留给时间戳+参数对
//获取需要进行MD5校验的内容:接口时间+内容	


//数据的加密和解密:简单的数据和秘钥进行相加
ms_u32 msdenc_api_encDec_simple(ms_byte* ms_in data, ms_u32 ms_in len,ms_byte * ms_in key,ms_s08 ms_in keylen,
		ms_byte * ms_out outbuf,ms_in ms_bool flag_enc) 
{
	ms_pamcheckRet(-1, data, "data");
	ms_pamcheckRet(-1, key, "key");
	ms_pamcheckRet(-1, outbuf, "outbuf");

	ms_u32 index=0;
	ms_s08 key_index=0;
	for(index=0;index<len;index++){
		if(ms_true==flag_enc){
			outbuf[index]=data[index]+key[key_index];
		}else{
			outbuf[index]=data[index]-key[key_index];
		}
		key_index+=1;
		if(keylen==key_index){
			key_index=0;
		}
	}
	return len;
}
//数据的加密和解密
ms_u32 msdenc_api_strMD5Enc(ms_byte*  data, ms_u32      len,ms_byte * key,ms_s08 keylen,ms_byte * strMD5) 
{
	ms_pamcheckRet(-1, data, "data");
	ms_pamcheckRet(-1, key, "key");
	ms_pamcheckRet(-1, strMD5, "outbuf");
	ms_byte bufin[LEN_MD5DATA]={0};
	ms_strcpy(bufin, data);
	ms_strcat(bufin,key);
	ms_u32 datalen=msmd5_api_outStr(bufin, (len+keylen), strMD5);
#if 0	
	ms_debug("enc-len,keylen:%d,%d",len,keylen);
	ms_debug("enc-bufin:%s",data);
	ms_debug("enc-bufin:%s",key);
	ms_debug("enc-bufin:%s",bufin);
	ms_debug("enc-strMD5:%s",strMD5);
#endif
	return datalen;
}
ms_bool msdenc_api_strMD5Check(ms_byte* strMD5,ms_byte*  data, ms_u32 len,ms_byte * key,ms_s08 keylen) 
{
	ms_pamcheckRet(-1, data, "data");
	ms_pamcheckRet(-1, key, "key");
	ms_pamcheckRet(-1, strMD5, "outbuf");
	
	ms_byte strMD5_calac[32]={0};
	//ms_debug("Check---------------------------");
	msdenc_api_strMD5Enc(data, len, key, keylen, strMD5_calac);
#if 0	
	ms_debug("Check-data:%s",data);
	ms_debug("Check-strMD5:%s",strMD5);
	ms_debug("Check-strMD5_calac:%s",strMD5_calac);
#endif
	return (ms_strncmp_saeq(strMD5_calac, strMD5))? ms_true : ms_false;
}

ms_void msdenc_api_encStr(ms_string     outstr,ms_string pbasekey,ms_string context,ms_string prefmt,ms_string aftfmt)
{
	ms_pamcheck( outstr, "outstr");
	ms_pamcheck(pbasekey, "pbasekey");
	ms_pamNocheck(context);
	ms_pamNocheck(prefmt);
	ms_pamNocheck(aftfmt);
	
	ms_u08 tbuf[256]={0};
//拼接前缀：无效干扰	
	if(ms_null!=prefmt){
		ms_strcats(tbuf,outstr, "%s&",prefmt);
	}
//拼接内容	
	//获取需要进行MD5校验的内容:接口时间+内容
	ms_s08 pStrSinnum[64]={0};
	mstime_api_curDTime(mstime_fmt_datetime_ex3,pStrSinnum);
	ms_byte md5Data[LEN_MD5DATA]={0};
	ms_strcpy(md5Data, pStrSinnum);
	if(ms_null!=context){
		if(ms_buflen(context)>MAXLEN_DENC_CONTENT){
			ms_fix("Oh my god,what?ms_buflen(context)=%d>%d",ms_buflen(context),MAXLEN_DENC_CONTENT);
		}else{
			ms_strcat(md5Data, context);
		}
	}
	//对当前时间和BASEKEY进行加密,计算出MD5值
	ms_byte strMD5[128]={0};
	msdenc_api_strMD5Enc(md5Data, ms_buflen(md5Data), pbasekey, ms_buflen(pbasekey), strMD5);
	ms_strcats(tbuf,outstr,  "%s%s&%s%s", KEYNAME_TIMECODE,pStrSinnum,KEYNAME_KEYCODE,strMD5);
//拼接结尾：无效干扰	
	if(ms_null!=aftfmt){
		ms_strcats(tbuf,outstr, "&%s",aftfmt);
	}
}
ms_void msdenc_api_encStr2(ms_string     outstr,ms_string pbasekey,ms_string context,ms_string moduleName,ms_string extStr)
{
	ms_pamcheck( outstr, "outstr");
	ms_pamcheck(pbasekey, "pbasekey");
	ms_pamNocheck(context);
	ms_byte prefmt[1024]={0};
	ms_sprintfs(prefmt, "module=%s",moduleName);
	msdenc_api_encStr(outstr, pbasekey, context, prefmt, extStr);
}

/*
解密字符串，并判定是否超时。返回值：
2：授权验证通过,超级字符串；
1：授权验证通过；
0：授权验证失败，授权超时
-1：授权验证失败
	instr:待解析的鉴权字符串token
	pbasekey:秘钥
	context:加密内容
	flag_mustdecrypt:是否需要进行鉴权
	timeou_sec:字符串token的有效期
*/
DECSTRRet msdenc_api_decStr(ms_string ms_in token,ms_string ms_in pbasekey,ms_string ms_in context,
	ms_bool ms_in flag_mustdecrypt,ms_u64 ms_in timeou_sec)
{
	ms_pamcheckRet(decstr_ret_noToken, token, "token");
	ms_pamcheckRet(decstr_ret_innerErr, pbasekey, "pbasekey");

	ms_u08 temp[2048]={0};
	ms_u08 pStrSinnum[128]={0};
	ms_u08 pStrKey[128]={0};
	if(0==ms_buflen(token) ){
		ms_warRet(decstr_ret_noToken,"no token");
	}
	if(msstr_api_isCasestr(token, enp_exstring_super)){
		return decstr_ret_super;
	}
	if(ms_false==flag_mustdecrypt){
		return decstr_ret_ok;
	}
	/*解析输入字符串，获取key=val值*/
//从instr获取接口时间和MD5值
	ms_strcpy(temp, token);
	ms_string str_array_item1[256];
	ms_u08 num=msstr_api_split(temp, "?", str_array_item1);
	if(num>1){
		ms_string str_array_item2[256];
		//ms_debug("---------%s",str_array_item1[1]);
		num=msstr_api_split(str_array_item1[1], "&", str_array_item2);
		ms_u08 index=0;
		for(index=0; index<num;index++){
			//ms_debug("---------%s",str_array_item2[index]);
			if( ms_strncmp_seq(str_array_item2[index],KEYNAME_TIMECODE)){
				ms_strcpy(pStrSinnum, &str_array_item2[index][ms_buflen(KEYNAME_TIMECODE)]);
				//ms_debug("pcurtime_basestr--------%s",pStrSinnum);
			}else if( ms_strncmp_seq(str_array_item2[index],KEYNAME_KEYCODE)){
				ms_strcpy(pStrKey, &str_array_item2[index][ms_buflen(KEYNAME_KEYCODE)]);
				//ms_debug("pcurtime_encstr--------%s",pStrKey);
			}
		}
	}
	if((0==ms_buflen(pStrSinnum))||(0==ms_buflen(pStrKey))){
		ms_warRet(decstr_ret_errToken1, "No %s and %s,token:%s",KEYNAME_TIMECODE,KEYNAME_KEYCODE,token);
	}

//拼接内容	
	//获取需要进行MD5校验的内容:接口时间+内容	
	ms_byte md5Data[LEN_MD5DATA]={0};
	ms_strcpy(md5Data, pStrSinnum);
	if(ms_null!=context){
		if(ms_buflen(context)>MAXLEN_DENC_CONTENT){
			ms_fix("Oh my god,what?ms_buflen(context)=%d>%d",ms_buflen(context),MAXLEN_DENC_CONTENT);
		}else{
			ms_strcat(md5Data, context);
		}
	}	
	/*解密并比较超时时间*/
	if( ms_true==msdenc_api_strMD5Check(pStrKey, md5Data, ms_buflen(md5Data),pbasekey, ms_buflen(pbasekey))){
		ms_u08 pstr[256]={0};
		ms_s08 strCurDTime[64]={0};
		ms_sprintfs(pstr, "B%sE%s", pStrSinnum,mstime_api_curDTime(mstime_fmt_datetime_ex3,strCurDTime))
		RSTime  ptm_time_base;
		RSTime  ptm_curtime_base;
		//ms_debug("---------%s",pstr);
		mstime_api_parsetimestr1( pstr, &ptm_time_base, &ptm_curtime_base,ms_null);
		if(ms_true==mstime_api_timeout3( &ptm_time_base, &ptm_curtime_base, timeou_sec)){
			ms_warRet(decstr_ret_timeout,"timeout");
		}else{
			return decstr_ret_ok;
		}
	}else{
		ms_warRet(decstr_ret_checkFailed,"check failed");
	}
}

#undef MSDENC_C

